/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package dao;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import bean.Chauffeur;
import bean.Agent;
import bean.Client;
import bean.Contrat;
import bean.Reservation;
import dao.exceptions.IllegalOrphanException;
import dao.exceptions.NonexistentEntityException;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author mezouari
 */
public class ReservationJpaController implements Serializable {

    public ReservationJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Reservation reservation) {
        if (reservation.getContratList() == null) {
            reservation.setContratList(new ArrayList<Contrat>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Chauffeur idChauffeur = reservation.getIdChauffeur();
            if (idChauffeur != null) {
                idChauffeur = em.getReference(idChauffeur.getClass(), idChauffeur.getId());
                reservation.setIdChauffeur(idChauffeur);
            }
            Agent idAgent = reservation.getIdAgent();
            if (idAgent != null) {
                idAgent = em.getReference(idAgent.getClass(), idAgent.getId());
                reservation.setIdAgent(idAgent);
            }
            Client idClient = reservation.getIdClient();
            if (idClient != null) {
                idClient = em.getReference(idClient.getClass(), idClient.getId());
                reservation.setIdClient(idClient);
            }
            List<Contrat> attachedContratList = new ArrayList<Contrat>();
            for (Contrat contratListContratToAttach : reservation.getContratList()) {
                contratListContratToAttach = em.getReference(contratListContratToAttach.getClass(), contratListContratToAttach.getId());
                attachedContratList.add(contratListContratToAttach);
            }
            reservation.setContratList(attachedContratList);
            em.persist(reservation);
            if (idChauffeur != null) {
                idChauffeur.getReservationList().add(reservation);
                idChauffeur = em.merge(idChauffeur);
            }
            if (idAgent != null) {
                idAgent.getReservationList().add(reservation);
                idAgent = em.merge(idAgent);
            }
            if (idClient != null) {
                idClient.getReservationList().add(reservation);
                idClient = em.merge(idClient);
            }
            for (Contrat contratListContrat : reservation.getContratList()) {
                Reservation oldIdReservationOfContratListContrat = contratListContrat.getIdReservation();
                contratListContrat.setIdReservation(reservation);
                contratListContrat = em.merge(contratListContrat);
                if (oldIdReservationOfContratListContrat != null) {
                    oldIdReservationOfContratListContrat.getContratList().remove(contratListContrat);
                    oldIdReservationOfContratListContrat = em.merge(oldIdReservationOfContratListContrat);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Reservation reservation) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Reservation persistentReservation = em.find(Reservation.class, reservation.getId());
            Chauffeur idChauffeurOld = persistentReservation.getIdChauffeur();
            Chauffeur idChauffeurNew = reservation.getIdChauffeur();
            Agent idAgentOld = persistentReservation.getIdAgent();
            Agent idAgentNew = reservation.getIdAgent();
            Client idClientOld = persistentReservation.getIdClient();
            Client idClientNew = reservation.getIdClient();
            List<Contrat> contratListOld = persistentReservation.getContratList();
            List<Contrat> contratListNew = reservation.getContratList();
            List<String> illegalOrphanMessages = null;
            for (Contrat contratListOldContrat : contratListOld) {
                if (!contratListNew.contains(contratListOldContrat)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Contrat " + contratListOldContrat + " since its idReservation field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (idChauffeurNew != null) {
                idChauffeurNew = em.getReference(idChauffeurNew.getClass(), idChauffeurNew.getId());
                reservation.setIdChauffeur(idChauffeurNew);
            }
            if (idAgentNew != null) {
                idAgentNew = em.getReference(idAgentNew.getClass(), idAgentNew.getId());
                reservation.setIdAgent(idAgentNew);
            }
            if (idClientNew != null) {
                idClientNew = em.getReference(idClientNew.getClass(), idClientNew.getId());
                reservation.setIdClient(idClientNew);
            }
            List<Contrat> attachedContratListNew = new ArrayList<Contrat>();
            for (Contrat contratListNewContratToAttach : contratListNew) {
                contratListNewContratToAttach = em.getReference(contratListNewContratToAttach.getClass(), contratListNewContratToAttach.getId());
                attachedContratListNew.add(contratListNewContratToAttach);
            }
            contratListNew = attachedContratListNew;
            reservation.setContratList(contratListNew);
            reservation = em.merge(reservation);
            if (idChauffeurOld != null && !idChauffeurOld.equals(idChauffeurNew)) {
                idChauffeurOld.getReservationList().remove(reservation);
                idChauffeurOld = em.merge(idChauffeurOld);
            }
            if (idChauffeurNew != null && !idChauffeurNew.equals(idChauffeurOld)) {
                idChauffeurNew.getReservationList().add(reservation);
                idChauffeurNew = em.merge(idChauffeurNew);
            }
            if (idAgentOld != null && !idAgentOld.equals(idAgentNew)) {
                idAgentOld.getReservationList().remove(reservation);
                idAgentOld = em.merge(idAgentOld);
            }
            if (idAgentNew != null && !idAgentNew.equals(idAgentOld)) {
                idAgentNew.getReservationList().add(reservation);
                idAgentNew = em.merge(idAgentNew);
            }
            if (idClientOld != null && !idClientOld.equals(idClientNew)) {
                idClientOld.getReservationList().remove(reservation);
                idClientOld = em.merge(idClientOld);
            }
            if (idClientNew != null && !idClientNew.equals(idClientOld)) {
                idClientNew.getReservationList().add(reservation);
                idClientNew = em.merge(idClientNew);
            }
            for (Contrat contratListNewContrat : contratListNew) {
                if (!contratListOld.contains(contratListNewContrat)) {
                    Reservation oldIdReservationOfContratListNewContrat = contratListNewContrat.getIdReservation();
                    contratListNewContrat.setIdReservation(reservation);
                    contratListNewContrat = em.merge(contratListNewContrat);
                    if (oldIdReservationOfContratListNewContrat != null && !oldIdReservationOfContratListNewContrat.equals(reservation)) {
                        oldIdReservationOfContratListNewContrat.getContratList().remove(contratListNewContrat);
                        oldIdReservationOfContratListNewContrat = em.merge(oldIdReservationOfContratListNewContrat);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = reservation.getId();
                if (findReservation(id) == null) {
                    throw new NonexistentEntityException("The reservation with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Reservation reservation;
            try {
                reservation = em.getReference(Reservation.class, id);
                reservation.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The reservation with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Contrat> contratListOrphanCheck = reservation.getContratList();
            for (Contrat contratListOrphanCheckContrat : contratListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Reservation (" + reservation + ") cannot be destroyed since the Contrat " + contratListOrphanCheckContrat + " in its contratList field has a non-nullable idReservation field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Chauffeur idChauffeur = reservation.getIdChauffeur();
            if (idChauffeur != null) {
                idChauffeur.getReservationList().remove(reservation);
                idChauffeur = em.merge(idChauffeur);
            }
            Agent idAgent = reservation.getIdAgent();
            if (idAgent != null) {
                idAgent.getReservationList().remove(reservation);
                idAgent = em.merge(idAgent);
            }
            Client idClient = reservation.getIdClient();
            if (idClient != null) {
                idClient.getReservationList().remove(reservation);
                idClient = em.merge(idClient);
            }
            em.remove(reservation);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Reservation> findReservationEntities() {
        return findReservationEntities(true, -1, -1);
    }

    public List<Reservation> findReservationEntities(int maxResults, int firstResult) {
        return findReservationEntities(false, maxResults, firstResult);
    }

    private List<Reservation> findReservationEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Reservation.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Reservation findReservation(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Reservation.class, id);
        } finally {
            em.close();
        }
    }

    public int getReservationCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Reservation> rt = cq.from(Reservation.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
